/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "pluginUrlContainer.h"

PluginUrlContainer::PluginUrlContainer()
{
    activePlugin = -1;
}

PluginUrlContainer::~PluginUrlContainer()
{

}

void PluginUrlContainer::start()
{
    if(activePlugin >= 0 && activePlugin < plugins.size())
    {
        plugins.at(activePlugin)->urlContainerInterface->start(activeUrl, captchaDir);
    } else
    {
        emit finished(QStringList(), true);
    }
}

void PluginUrlContainer::abort()
{
    if(activePlugin >= 0 && activePlugin < plugins.size())
    {
        plugins.at(activePlugin)->urlContainerInterface->abort();
    } else
    {
        emit finished(QStringList(), true);
    }
}

void PluginUrlContainer::submitCaptcha(QString const& captcha)
{
    if(activePlugin >= 0 && activePlugin < plugins.size())
    {
        plugins.at(activePlugin)->urlContainerInterface->setCaptcha(captcha);
    } else
    {
        emit finished(QStringList(), true);
    }
}

bool PluginUrlContainer::isUrlContainer(QUrl const& url)
{
    for(int i=0; i<plugins.size(); ++i)
    {
        if(plugins.at(i)->urlContainerInterface->isValidUrl(url)) return true;
    }

    return false;
}

bool PluginUrlContainer::isUrlContainer(QString const& link)
{
    return isUrlContainer(QUrl(link));
}

bool PluginUrlContainer::selectPluginForLink(QUrl const& url)
{
    if(activePlugin >= 0 && activePlugin < plugins.size())
    {
        disconnect(plugins.at(activePlugin)->urlContainerObject, 0, this, 0);
    }

    for(int i=0; i<plugins.size(); ++i)
    {
        if(plugins.at(i)->urlContainerInterface->isValidUrl(url))
        {
            activePlugin = i;
            activeUrl = url;

            connect(plugins.at(activePlugin)->urlContainerObject, SIGNAL(finished(QStringList const&, bool const&)), this, SLOT(slot_plugin_finished(QStringList const&, bool const&)));
            connect(plugins.at(activePlugin)->urlContainerObject, SIGNAL(captcha(QString const&)), this, SLOT(slot_plugin_captcha(QString const&)));
            connect(plugins.at(activePlugin)->urlContainerObject, SIGNAL(stateChanged()), this, SLOT(slot_plugin_stateChanged()));
            connect(plugins.at(activePlugin)->urlContainerObject, SIGNAL(progressChanged(int const&)), this, SLOT(slot_plugin_progressChanged(int const&)));

            return true;
        }
    }

    activePlugin = -1;
    return false;
}

bool PluginUrlContainer::selectPluginForLink(QString const& link)
{
    return selectPluginForLink(QUrl(link));
}

void PluginUrlContainer::setProxy(QNetworkProxy const& proxy)
{
    _proxy = QNetworkProxy(proxy);
    for(int i=0; i<plugins.size(); ++i)
    {
        plugins.at(i)->urlContainerInterface->setProxy(proxy);
    }
}

void PluginUrlContainer::loadPlugins(QDir pluginDir)
{
    //todo: unload first

    if(pluginDir.exists())
    {
        pluginDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);

        QStringList tmpList;
        tmpList << "*.so" << "*.dll";
        pluginDir.setNameFilters(tmpList);

        QFileInfoList list = pluginDir.entryInfoList();

        for(int i=0; i<list.size(); ++i)
        {
            QFileInfo fileInfo = list.at(i);

            QFile tmpFile(fileInfo.absoluteFilePath());

            if(tmpFile.exists())
            {
                QString pluginFile = tmpFile.fileName();

                QPluginLoader *pluginLoader = new QPluginLoader(pluginFile);
                QObject *urlContainerObject = pluginLoader->instance();
                InterfaceUrlContainer *urlContainerInterface = 0;

                if(urlContainerObject)
                {
                    urlContainerInterface = qobject_cast<InterfaceUrlContainer *>(urlContainerObject);

                    if(urlContainerInterface)
                    {
                        S_PLUGIN * plugin = new S_PLUGIN();

                        plugin->pluginFile = pluginFile;
                        plugin->pluginLoader = pluginLoader;
                        plugin->urlContainerObject = urlContainerObject;
                        plugin->urlContainerInterface = urlContainerInterface;

                        plugins.append(plugin);

                        emit errorMsg("loaded: " + fileInfo.fileName());
                        continue;
                    } else
                    {
                        emit errorMsg(pluginLoader->errorString());

                        urlContainerObject->deleteLater();
                        pluginLoader->unload();
                        pluginLoader->deleteLater();
                        continue;
                    }
                } else
                {                    
                    emit errorMsg(pluginLoader->errorString());

                    pluginLoader->unload();
                    pluginLoader->deleteLater();
                    continue;
                }
            } else
            {
                emit errorMsg("file not found: " + tmpFile.fileName());
            }
        }
    }
}

void PluginUrlContainer::slot_plugin_finished(QStringList const& links, bool const& error)
{
    emit finished(links, error);
}

void PluginUrlContainer::slot_plugin_captcha(QString const& _captcha)
{
    emit captcha(_captcha);
}

void PluginUrlContainer::slot_plugin_stateChanged()
{
    emit stateChanged();
}

void PluginUrlContainer::slot_plugin_progressChanged(int const& progress)
{
    emit progressChanged(progress);
}
